package com.ruoyi.finance.collection.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ice.core.context.IceRoam;
import com.ruoyi.base.domain.SProjectFee;
import com.ruoyi.base.service.impl.SProjectFeeServiceImpl;
import com.ruoyi.business.projectRecord.domain.ProjectRecord;
import com.ruoyi.business.projectRecord.service.ProjectRecordService;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.contract.domain.ConRule;
import com.ruoyi.contract.service.ConRuleService;
import com.ruoyi.finance.collection.domain.BillCollection;
import com.ruoyi.finance.collection.domain.VBillCollection;
import com.ruoyi.finance.collection.domain.validation.VBillCollectionLeftJoinVProjectTos;
import com.ruoyi.finance.collection.domain.vo.ChargeElementsVo;
import com.ruoyi.finance.collection.mapper.BillCollectionMapper;
import com.ruoyi.finance.collection.mapper.VBillCollectionMapper;
import com.ruoyi.finance.collection.service.BillCollectionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

/**
 * @author 80661
 * @description 针对表【BILL_COLLECTION(收款费项表)】的数据库操作Service实现
 * @createDate 2023-07-04 15:02:31
 */
@Service
public class BillCollectionServiceImpl extends ServiceImpl<BillCollectionMapper, BillCollection>
        implements BillCollectionService {


    @Autowired
    private ConRuleService conRuleService;

    @Autowired
    ProjectRecordService projectRecordService;

    @Autowired
    ChargeElementServiceImpl chargeElementService;

    @Autowired
    SProjectFeeServiceImpl sProjectFeeService;
    
    @Autowired
    VBillCollectionMapper vBillCollectionMapper;
    
    @Autowired
    BillCollectionMapper billCollectionMapper;
    

    @Override
    public List<BillCollection> listByParams(BillCollection billCollection) {
        // 1.创建QueryWrapper
        QueryWrapper<BillCollection> queryWrapper = new QueryWrapper<>();

        // 2.构造查询条件


        // 3.执行查询
        List<BillCollection> billCollectionList = this.list(queryWrapper);

        // 4.返回结果
        return billCollectionList;

    }

    /**
     * 自动收款
     *
     * @param projectId
     * @return
     */
    @Override
    public AjaxResult autoCollection(Long projectId) {
        // 1.根据项目id查询项目信息
        HashMap calMap = new HashMap();
        ProjectRecord projectRecord = projectRecordService.getById(projectId);
        // 2.根据项目Id和项目类型查询计费要素
        List<ChargeElementsVo> chargeElementsVos = chargeElementService.selectByProjectIdAndType(projectId, projectRecord.getProjectType());
        // 3.计费要素写入map
        for (ChargeElementsVo chargeElementsVo : chargeElementsVos) {
            calMap.put(chargeElementsVo.getElementsCode(), chargeElementsVo.getElementsNum());
        }
        // 错误情况1 计费要素为空
        if (chargeElementsVos.size() == 0) {
            return AjaxResult.error("计费要素为空");
        }
        // 得到计费结果
        List<IceRoam> iceRoams = conRuleService.autoCal(projectRecord.getConId(), projectRecord.getProjectType(), calMap);
        System.out.println(iceRoams);
        // 错误情况2 计费结果为空
        if (iceRoams.size() == 0) {
            return AjaxResult.error("计费结果为空");
        }
        // 对于每个计费结果，生成费项
        List<BillCollection> autoCollectionList = this.getAutoCollectionList(iceRoams, projectRecord);
        // 错误情况3 生成费项为空
        if (autoCollectionList.size() == 0) {
            return AjaxResult.error("没有需要生成的费项，已手动计费或自动计费费项已经手动修改或已对账");
        }
        // 插入或者更新费项
        for (BillCollection billCollection : autoCollectionList) {
            // 有ID的更新，没有ID的插入
            if (billCollection.getBillCollectionId() != null) {
                this.updateById(billCollection);
            } else {
                this.save(billCollection);
            }
        }
        return AjaxResult.success("计费成功");
    }
    @Override
    public AjaxResult autoCollectionall(Long[] projectIds) {
        Long m = System.currentTimeMillis();
        // 1.查出对应计费类型的计费要素 因为查计费要素太耗时了，所以先一次性都查出来
        //获取projectType
        ProjectRecord projectRecord1 = projectRecordService.getById(projectIds[0]);
        String projectType = projectRecord1.getProjectType();
        //记录chargeElementService.selectByProjectIdAndType 运行开始时间
        long start = System.currentTimeMillis();
        List<ChargeElementsVo> chargeElementsVos = chargeElementService.selectByProjectIdAndTypeFromTable(projectType);
        //记录chargeElementService.selectByProjectIdAndType 运行结束时间
        long end = System.currentTimeMillis();
        System.out.println("chargeElementService.selectByProjectIdAndType 运行时间：" + (end - start) + "ms");
//        // 串行计费
//        // 遍历projectIds
//        for(Long projectId : projectIds){
//            // 2.根据项目id查询项目信息
//            HashMap calMap = new HashMap();
//            ProjectRecord projectRecord = projectRecordService.getById(projectId);
//
//            // 3.计费要素写入map
//            for (ChargeElementsVo chargeElementsVo : chargeElementsVos) {
//                //根据合同id和type把计费要素写入map
//                if(chargeElementsVo.getProjectId().equals(projectId)&&chargeElementsVo.getProjectType().equals(projectRecord.getProjectType())){
//                    calMap.put(chargeElementsVo.getElementsCode(), chargeElementsVo.getElementsNum());
//                }
//            }
//            // 错误情况1 计费要素为空
//            if (chargeElementsVos.size() == 0) {
//                // 去视图再次查询
//                List<ChargeElementsVo> chargeElementsVosFromView = chargeElementService.selectByProjectIdAndType2(projectType,projectId);
//                if (chargeElementsVosFromView.size()==0){
//                    return AjaxResult.error("计费要素为空");
//                } else {
//                    for (ChargeElementsVo chargeElementsVoFromVied : chargeElementsVosFromView){
//                        calMap.put(chargeElementsVoFromVied.getElementsCode(), chargeElementsVoFromVied.getElementsNum());
//                    }
//                }
//
//            }
//            // 得到计费结果
//
//            List<IceRoam> iceRoams = conRuleService.autoCal(projectRecord.getConId(), projectRecord.getProjectType(), calMap);
//
//            // 错误情况2 计费结果为空
//            if (iceRoams.size() == 0) {
//                return AjaxResult.error("计费结果为空");
//            }
//            // 对于每个计费结果，生成费项
//            List<BillCollection> autoCollectionList = this.getAutoCollectionList(iceRoams, projectRecord);
//            // 错误情况3 生成费项为空
//            if (autoCollectionList.size() == 0) {
//                return AjaxResult.error("没有需要生成的费项，已手动计费或自动计费费项已经手动修改或已对账");
//            }
//            // 插入或者更新费项
//            for (BillCollection billCollection : autoCollectionList) {
//                // 有ID的更新，没有ID的插入
//                if (billCollection.getBillCollectionId() != null) {
//                    this.updateById(billCollection);
//                } else {
//                    this.save(billCollection);
//                }
//            }
//        }

        // 并行计费
        ConcurrentLinkedQueue<Long> concurrentLinkedQueue = new ConcurrentLinkedQueue<>(Arrays.asList(projectIds));
        ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
        concurrentLinkedQueue.parallelStream().forEach(projectId -> {
            try {
                // 2.根据项目id查询项目信息
                HashMap calMap = new HashMap();
                ProjectRecord projectRecord = projectRecordService.getById(projectId);

                // 3.计费要素写入map
                for (ChargeElementsVo chargeElementsVo : chargeElementsVos) {
                    //根据合同id和type把计费要素写入map
                    if(chargeElementsVo.getProjectId().equals(projectId)&&chargeElementsVo.getProjectType().equals(projectRecord.getProjectType())){
                        calMap.put(chargeElementsVo.getElementsCode(), chargeElementsVo.getElementsNum());
                    }
                }
                // 错误情况1 计费要素为空
                if (chargeElementsVos.size() == 0) {
                    // 去视图再次查询
                    List<ChargeElementsVo> chargeElementsVosFromView = chargeElementService.selectByProjectIdAndTypeFromView(projectType,projectId);
                    if (chargeElementsVosFromView.size()==0){
                        throw new RuntimeException("计费要素为空");
                    } else {
                        for (ChargeElementsVo chargeElementsVoFromVied : chargeElementsVosFromView){
                            calMap.put(chargeElementsVoFromVied.getElementsCode(), chargeElementsVoFromVied.getElementsNum());
                        }
                    }

                }
                // 得到计费结果

                List<IceRoam> iceRoams = conRuleService.autoCal(projectRecord.getConId(), projectRecord.getProjectType(), calMap);

                // 错误情况2 计费结果为空
                if (iceRoams.size() == 0) {
                    throw new RuntimeException("计费结果为空");
                }
                // 对于每个计费结果，生成费项
                List<BillCollection> autoCollectionList = this.getAutoCollectionList(iceRoams, projectRecord);
                // 错误情况3 生成费项为空
                if (autoCollectionList.size() == 0) {
                    throw new RuntimeException("没有需要生成的费项，已手动计费或自动计费费项已经手动修改或已对账");
                }
                // 插入或者更新费项
                for (BillCollection billCollection : autoCollectionList) {
                    System.out.println(billCollection);
                    // 有ID的更新，没有ID的插入
                    if (billCollection.getBillCollectionId() != null) {
                        this.updateById(billCollection);
                    } else {
                        billCollectionMapper.insert(billCollection);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
        executorService.shutdown();
        

        Long n = System.currentTimeMillis();
        System.out.println("计费耗时" + (n-m) + "ms");

        return AjaxResult.success("计费成功");

    }
    @Override
    public void setBasicFeeCodeAndName(BillCollection billCollection) {
        // 二级费目ID不为空，根据二级费目ID查询projectFee信息
        if (billCollection.getFeeServiceId() != null) {
            SProjectFee projectFee = sProjectFeeService.getById(billCollection.getFeeServiceId());
            billCollection.setBasicFeeCode(projectFee.getFeeType());
            billCollection.setBasicFeeName(baseMapper.selectBasicFeeName(projectFee.getFeeType()));
        }
    }

    // 根据计费结果得到所需生成费项列表
    public List<BillCollection> getAutoCollectionList(List<IceRoam> iceRoams, ProjectRecord projectRecord) {
        List<BillCollection> billCollectionList = new ArrayList<>();
        System.out.println("iceRoams"+iceRoams);
        for (IceRoam iceRoam : iceRoams) {
            BillCollection billCollection = new BillCollection();
            billCollection.setProjectId(projectRecord.getProjectId());
            billCollection.setGkey(projectRecord.getGkey());
            billCollection.setConId(projectRecord.getConId());
            billCollection.setCustomerCod(projectRecord.getCustomerCod());
            billCollection.setCustomerNam(projectRecord.getCustomerNam());
            billCollection.setCompanyCod(projectRecord.getCompanyCod());
            billCollection.setAmount(new BigDecimal(iceRoam.get("finalResult").toString()));
            // rule,得到二级费目ID
            ConRule conRule = conRuleService.getById(iceRoam.get("ruleId").toString());
            billCollection.setCurrency(conRule.getCurrency());
            billCollection.setRuleId(conRule.getRuleId());
            // 赋值 单价 税率 workNum  workNumB
            billCollection.setTaxRate(conRule.getTaxRate());
            if(iceRoam.containsKey("unitPrice")){
                billCollection.setUnitPrice(new BigDecimal(iceRoam.get("unitPrice").toString()));
            }
            if(iceRoam.containsKey("workNum1")){
                billCollection.setWorkNum(new BigDecimal(iceRoam.get("workNum1").toString()));
            }
            if(iceRoam.containsKey("workDays")){
                billCollection.setWorkNumB(new BigDecimal(iceRoam.get("workDays").toString()));
            }
            if(iceRoam.containsKey("remark")){
                billCollection.setRemark(iceRoam.get("remark").toString());
            }
//            billCollection.setUnitPrice(new BigDecimal(iceRoam.get("unitPrice").toString()));
//            billCollection.setWorkNum(new BigDecimal(iceRoam.get("workNum1").toString()));
//            billCollection.setWorkNumB(new BigDecimal(iceRoam.get("workDays").toString()));
            SProjectFee projectFee = sProjectFeeService.getById(conRule.getProjectId());
            // 赋值二级费目ID 二级费目名称 一级费目Code 一级费目名称
            billCollection.setFeeServiceId(projectFee.getProjectFeeId());
            billCollection.setFeeServiceName(projectFee.getProjectFeeName());
            billCollection.setBasicFeeCode(projectFee.getFeeType());
            billCollection.setBasicFeeName(baseMapper.selectBasicFeeName(projectFee.getFeeType()));
            // 费项来源 2 自动计费
            billCollection.setCollectionSource("2");
            // 查询该费目是否已经生成费项
            BillCollection billCollection1 = baseMapper.selectByProjectIdAndRateId(billCollection.getProjectId(), billCollection.getRuleId());
            if (billCollection1 != null) {
                // 需要更新的情况 自动计费费项，且没被修改过，状态为初始
                if ("2".equals(billCollection1.getCollectionSource()) && "0".equals(billCollection1.getCollectionStatus())) {
                    billCollection.setBillCollectionId(billCollection1.getBillCollectionId());
                    billCollectionList.add(billCollection);
                }
            } else {
                // 无费项，直接插入
                billCollectionList.add(billCollection);
            }
        }
        return billCollectionList;
    }

    @Override
    public List<VBillCollection> listVBCollectionByStatementId(Long statementId) {
        return vBillCollectionMapper.listVBCollectionByStatementId(statementId);
    }

    @Override
    public List<BillCollection> listBillCollectionByStatementId(Long statementId) {
        return baseMapper.listBillCollectionByStatementId(statementId);
    }

    @Override
    public boolean updateByStatementId(Long statementId) {
        return baseMapper.updateByStatementId(statementId);
    }

    @Override
    public void updateDelNameAndDelTime(Long billCollectionId, String delName, Date delTime) {
        baseMapper.updateDelNameAndDelTime(billCollectionId,delName,delTime);
    }

    /**
     * 去除billCollectionIdS中业务数据重复的BILL_COLLECTION_ID
     * @param billCollectionIdS
     * @param companyCod
     * @return
     */
    @Override
    public String distinguishBillCollectionIds(List<Long> billCollectionIdS,String companyCod) {
        // 新建uniqueBillCollectionIds用于存储去重后的费项ID
        List<Long> uniqueBillCollectionIds = new ArrayList<>();
        // 每种业务类型根据P_GEN_STATEMENT中对应的验证字段，建立一个验证列表来存储projectList中每个费项的业务数据，并进行数据是否重复的判断
        List<List<String>> discFeeValidList = new ArrayList<>();
        List<List<String>> bulkDiscFeeValidList = new ArrayList<>();
        List<String> truckFeeValidList = new ArrayList<>();
        List<String> imCyFeeValidList = new ArrayList<>();
        List<List<String>> exCyFeeValidList = new ArrayList<>();
        // 求billCollectionId的最长位数，加1是考虑到字符串中还要包含逗号分隔符
        Long maxId = Collections.max(billCollectionIdS);
        int digitCount = String.valueOf(maxId).length() + 1;
        // 求每一批次处理的Id个数，避免字符串过长导致SQL语句报错
        int batch = 2000/digitCount;
        // 分批次进行去重处理
        for (int i = 0;i < billCollectionIdS.size();i+=batch){
            List<Long> subBillCollectionIdS;
            if (i+batch-1<billCollectionIdS.size()){
                subBillCollectionIdS = billCollectionIdS.subList(i,i+batch);
            }else{
                subBillCollectionIdS = billCollectionIdS.subList(i,billCollectionIdS.size());
            }
            // subBillCollectionIdS列表拼接成字符串
            String pBillCollectionIds = subBillCollectionIdS.stream().map(String::valueOf).collect(Collectors.joining(","));
            // 根据pBillCollectionIds和companyCod获取业务数据
            List<VBillCollectionLeftJoinVProjectTos> projectList = vBillCollectionMapper.listVBillCollectionLeftJoinVProjectTos(pBillCollectionIds, companyCod);
            for(VBillCollectionLeftJoinVProjectTos item:projectList){
                // 获取费项的业务类型
                String projectType = item.getProjectType();
                if (projectType.equals("disc_fee")){
                    // 获取费项的“船名”和“航次”
                    List<String> discFeeDataList = new ArrayList<>(Arrays.asList(item.getShipNam(),item.getVoyage()));
                    // 判断验证列表discFeeValidList中是否已经存在该组数据
                    if (!discFeeValidList.contains(discFeeDataList)){
                        // 若discFeeValidList中不存在该组数据，说明该费项的业务数据不是重复的，将其添加至discFeeValidList，并将费项ID添加至uniqueBillCollectionIds
                        discFeeValidList.add(discFeeDataList);
                        uniqueBillCollectionIds.add(item.getBillCollectionId());

                        // 若discFeeValidList中存在该组数据，说明该费项的业务数据是重复的，需要去除，则跳过该费项

                        // 其余业务类型的处理逻辑相同
                    }
                }
                if (projectType.equals("bulk_disc_fee")){
                    List<String> bulkDiscFeeDataList = new ArrayList<>(Arrays.asList(item.getShipNam(),item.getVoyage(),item.getCustomerCod()));
                    if (!bulkDiscFeeValidList.contains(bulkDiscFeeDataList)){
                        bulkDiscFeeValidList.add(bulkDiscFeeDataList);
                        uniqueBillCollectionIds.add(item.getBillCollectionId());
                    }
                }
                if (projectType.equals("truck_fee")){
                    if (!truckFeeValidList.contains(item.getReservationNo())){
                        truckFeeValidList.add(item.getReservationNo());
                        uniqueBillCollectionIds.add(item.getBillCollectionId());
                    }
                }
                if (projectType.equals("cy_fee")){
                    if (item.getIeType().equals("im")){
                        if (!imCyFeeValidList.contains(item.getReservationNo())){
                            imCyFeeValidList.add(item.getReservationNo());
                            uniqueBillCollectionIds.add(item.getBillCollectionId());
                        }
                    }
                    if (item.getIeType().equals("ex")){
                        List<String> exCyFeeDataList = new ArrayList<>(Arrays.asList(item.getShipNam(),item.getVoyage()));
                        if (!exCyFeeValidList.contains(exCyFeeDataList)){
                            exCyFeeValidList.add(exCyFeeDataList);
                            uniqueBillCollectionIds.add(item.getBillCollectionId());
                        }
                    }
                }
            }
        }
        
        // 返回去重列表uniqueBillCollectionIds拼接而成的字符串
        return uniqueBillCollectionIds.stream().map(String::valueOf).collect(Collectors.joining(","));
    }
}




